package com.shimao.celnet.payment.controller.api;

import com.alibaba.druid.util.StringUtils;
import com.shimao.celnet.payment.model.PPay;
import com.shimao.celnet.payment.model.PPayCust;
import com.shimao.celnet.payment.model.PPayRefund;
import com.shimao.celnet.payment.model.request.CallIn_OutPayReqInRequest;
import com.shimao.celnet.payment.model.response.ErrorInfoEnum;
import com.shimao.celnet.payment.model.response.ResponseJson;
import com.shimao.celnet.payment.service.PPayCustService;
import com.shimao.celnet.payment.service.PPayRefundService;
import com.shimao.celnet.payment.service.PPayService;
import com.shimao.celnet.payment.service.impl.apiservice.CallOut_TLPublicService;
import com.shimao.celnet.payment.util.FinalUtil;
import com.shimao.celnet.payment.util.MyDateUtil;
import io.swagger.annotations.ApiOperation;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * christ
 * 接受外部系统：交易撤销和交易退款 处理
 * 交易撤销条件：交易日期在当天内，并且全额退款
 * 交易退款 ：部分退款，支付日期在88天内
 * 2017-12-20
 */
@RestController
@RequestMapping("/payment")
public class CallIn_outPayRefundInController {
    protected Logger logger = Logger.getLogger(this.getClass());
    @Autowired
    private PPayService pPayService;

    @Autowired
    private PPayRefundService pPayRefundService;

    @Autowired
    private PPayCustService pPayCustService;

    @Autowired
    private CallOut_TLPublicService callOut_tlPublicService;

    @ApiOperation("获取外部请求撤销，退款数据")
    @RequestMapping(value = "/refund", method = RequestMethod.POST)
    public Object outPayRefundInController(@RequestBody CallIn_OutPayReqInRequest callIn_outPayReqInRequest) {
        ResponseJson retJson = new ResponseJson(ErrorInfoEnum.SUCCESS, "");
        String reqsn = String.valueOf(System.currentTimeMillis());//随机数
        String paymentId = callIn_outPayReqInRequest.getPaymentId();
        String refundAmount = callIn_outPayReqInRequest.getRefundAmount();
        Long refundTotal = 0L;
        if (StringUtils.isEmpty(paymentId)) {
            logger.debug("缺少必要参数：" + paymentId);
            retJson = new ResponseJson(ErrorInfoEnum.NOT_PARAMS, "paymentId");
            return retJson.toString();
        }
        try {
            //当refundAmount不为整数的时候会抛出异常,利用异常判断refundAmount是否为整数
            if (Integer.valueOf(refundAmount) < 0){
                retJson = new ResponseJson(ErrorInfoEnum.ERROR_PARAMS, "refundAmount");
                logger.debug("请求金额异常：" + refundAmount);
                return retJson.toString();
            }
        }catch (NumberFormatException e){
            retJson = new ResponseJson(ErrorInfoEnum.ERROR_PARAMS, "refundAmount");
            logger.debug("请求金额异常：" + refundAmount);
            return retJson.toString();
        }
        //根据guid查询数据库中的账单表
        PPay pPay = pPayService.getByKey(paymentId);
        PPayCust pPayCust= getTLMessage(pPay.getEstateGuid(),pPay.getPayType());
        PPayRefund pPayRefund = pPayRefundService.selectListByMap(paymentId);
        //如果该支付订单已退款，就不能再进行退款
        if (pPayRefund != null && FinalUtil.PAY_REFUND_SUCCESS.equals(pPayRefund.getRefundStatus())){
            return new ResponseJson(ErrorInfoEnum.FAIL_REFUND, "该订单已经执行过退款！");
        }
        if(FinalUtil.CUP_PAY_TYPE.equals(pPay.getPayType())){
            //==========退款请求金额等于订单总额 & 小于订单总额==========
            if (Integer.valueOf(pPay.getPayAmount()) - Integer.valueOf(refundAmount) >= 0) {
                //==================交易日期在当天内，并且退款金额与支付金额相同============
                if (MyDateUtil.isThisTime(Long.valueOf(pPay.getPayEndTime()), MyDateUtil.format_yyyy_MM_dd) && Integer.valueOf(pPay.getPayAmount()) - Integer.valueOf(refundAmount) == 0) {
                    //================通联撤销处理：保存撤销数据==================
                    logger.info("================请求金额通联撤销开始================");
                    PPayRefund payCancel = new PPayRefund();
                    String guid =pPayRefundService.getGuid();
                    payCancel.setDeleteFlg("0");//删除标识 0代表未删除
                    payCancel.setCreatedDate(new Date());
                    payCancel.setRefundAmount(refundAmount);//撤销金额
                    payCancel.setRefundStartTime(String.valueOf(System.currentTimeMillis()));//撤销动作开始时间
                    payCancel.setOldTrxid(pPay.getTrxid());//原订单在收银宝的流水号，用于查账，撤销，退款
                    payCancel.setPayGuid(paymentId);//订单guis
                    payCancel.setGuid(guid);
                    //==================执行交易撤销================
                    try {
                    /*
                     * refundAmount 退款金额
                     * reqsn 随机数
                     * pPay.getTrxid() 原交易收银宝平台流水号
                     *oldreqsn	原交易单号	原交易的商户交易单号
                     * 只能撤销当天的交易，全额退款，实时返回退款结果
                     */
                        logger.info("当天撤销请求参数：payCancel"+payCancel.getOldTrxid()+" pPay"+pPay.getPayUserSfGuid()+" pPayCust"+pPayCust.getCustId());
                        Map<String, String> cancel = callOut_tlPublicService.cancelCUP(MyDateUtil.NotString(guid),Long.valueOf(refundAmount),MyDateUtil.NotString(pPay.getGuid()), pPay.getTrxid(),pPayCust);
                        logger.info("当天撤销响应参数"+cancel.toString());
                        if("0000".equals(cancel.get("trxstatus"))&&"SUCCESS".equals(cancel.get("retcode"))){
                            payCancel.setTrxid(cancel.get("trxid"));//交易撤销流水单号
                            payCancel.setRefundStatus(FinalUtil.PAY_REFUND_SUCCESS);//退款状态 0表示成功
                            payCancel.setRefundEndTime(String.valueOf(new SimpleDateFormat("yyyyMMddHHmmss").parse(cancel.get("fintime")).getTime()));
                        }else if("3012".equals(cancel.get("trxstatus"))&&"SUCCESS".equals(cancel.get("retcode"))){
                            payCancel.setRefundStatus(FinalUtil.PAY_REFUND_FAILUE);//退款失败
                            payCancel.setRefundEndTime(String.valueOf(new SimpleDateFormat("yyyyMMddHHmmss").parse(cancel.get("fintime")).getTime()));
                            retJson = new ResponseJson(ErrorInfoEnum.PAY_RESULT_TYPE,"原交易不允许撤销或退货");
                        }else if("3035".equals(cancel.get("trxstatus"))&&"SUCCESS".equals(cancel.get("retcode"))){
                            payCancel.setRefundStatus(FinalUtil.PAY_REFUND_FAILUE);//退款失败
                            payCancel.setRefundEndTime(String.valueOf(new SimpleDateFormat("yyyyMMddHHmmss").parse(cancel.get("fintime")).getTime()));
                            retJson = new ResponseJson(ErrorInfoEnum.PAY_RESULT_TYPE,"原交易不存在" );
                        }else if("1001".equals(cancel.get("trxstatus"))&&"SUCCESS".equals(cancel.get("retcode"))){
                            payCancel.setRefundStatus(FinalUtil.PAY_REFUND_FAILUE);//退款失败
                            payCancel.setRefundEndTime(String.valueOf(new SimpleDateFormat("yyyyMMddHHmmss").parse(cancel.get("fintime")).getTime()));
                            retJson = new ResponseJson(ErrorInfoEnum.PAY_RESULT_TYPE,"原交易不存在");
                        }else if("3054".equals(cancel.get("trxstatus"))&&"SUCCESS".equals(cancel.get("retcode"))){
                            payCancel.setRefundStatus("2");//交易异常,请查询交易
                            payCancel.setRefundEndTime(String.valueOf(new SimpleDateFormat("yyyyMMddHHmmss").parse(cancel.get("fintime")).getTime()));
                            retJson = new ResponseJson(ErrorInfoEnum.PAY_DATA_TYPE,"");
                        }else{
                            //保存交易撤销数据
                            payCancel.setRefundStatus(FinalUtil.PAY_REFUND_FAILUE);
                            retJson = new ResponseJson(ErrorInfoEnum.FAIL_REFUND,cancel.get("errmsg"));
                        }
                        pPayRefundService.save(payCancel);
                    } catch (Exception e) {
                        e.printStackTrace();
                        return retJson = new ResponseJson(ErrorInfoEnum.FAIL_REFUND, e.toString());
                    }
                }
                //==================交易日期在大于今天小于88天内============
                if (MyDateUtil.getDayDiffFromToday1(pPay.getPayEndTime())) {
                    //================存储退款数据==================
                    logger.info("================请求金额退款开始================");
                    PPayRefund PPayRefund = new PPayRefund();
                    String guid =pPayRefundService.getGuid();
                    PPayRefund.setDeleteFlg("0");//删除标识 0代表未删除
                    pPayRefund.setGuid(guid);
                    PPayRefund.setCreatedDate(new Date());
                    PPayRefund.setRefundAmount(refundAmount);//撤销金额
                    PPayRefund.setRefundStartTime(String.valueOf(System.currentTimeMillis()));//撤销动作开始时间
                    PPayRefund.setOldTrxid(pPay.getTrxid());//原订单在收银宝的流水号，用于查账，撤销，退款
                    PPayRefund.setPayGuid(paymentId);//订单guis
                    pPayRefund.setNotifyUrl(callIn_outPayReqInRequest.getNotifyUrl());
                    //==================执行退款===============
                    try {
                    /*
                     * refundAmount 退款金额
                     * reqsn 随机数
                     * pPay.getTrxid() 原交易收银宝平台流水号
                     *oldreqsn	原交易单号	原交易的商户交易单号
                     * 支持部分金额退款，隔天交易退款
                     */
                        logger.info("隔天退款请求参数：PPayRefund"+refundAmount+" pPay"+pPay.getTrxid()+" pPayCust"+pPayCust.toString());
                        Map<String, String> refund = callOut_tlPublicService.refundCUP(Long.valueOf(refundAmount), MyDateUtil.NotString(guid),MyDateUtil.NotString(pPay.getGuid()), pPay.getTrxid(),pPayCust);
                        logger.info("隔天退款响应参数："+refund.toString());
                        if (refund.keySet().contains("errmsg") && refund.get("errmsg").contains("余额不足")) {
                            retJson = new ResponseJson(ErrorInfoEnum.FAIL_REFUND, "退款账户余额不足");
                            PPayRefund.setTrxid(refund.get("trxid"));//交易撤销流水单号
                            PPayRefund.setRefundStatus(FinalUtil.PAY_REFUND_FAILUE);
                            PPayRefund.setRefundEndTime(String.valueOf(new SimpleDateFormat("yyyyMMddHHmmss").parse(refund.get("fintime")).getTime()));
                        } else {
                            if("0000".equals(refund.get("trxstatus"))&&"SUCCESS".equals(refund.get("retcode"))){
                                PPayRefund.setTrxid(refund.get("trxid"));//交易撤销流水单号
                                PPayRefund.setRefundStatus(FinalUtil.PAY_REFUND_SUCCESS);
                                PPayRefund.setRefundEndTime(String.valueOf(new SimpleDateFormat("yyyyMMddHHmmss").parse(refund.get("fintime")).getTime()));
                            }else if ("3035".equals(refund.get("trxstatus"))&&"SUCCESS".equals(refund.get("retcode"))){
                                PPayRefund.setRefundStatus(FinalUtil.PAY_REFUND_FAILUE);//退款失败
                                retJson = new ResponseJson(ErrorInfoEnum.PAY_RESULT_TYPE,"原交易不存在" );
                                PPayRefund.setRefundEndTime(String.valueOf(new SimpleDateFormat("yyyyMMddHHmmss").parse(refund.get("fintime")).getTime()));
                            }else if("3012".equals(refund.get("trxstatus"))&&"SUCCESS".equals(refund.get("retcode"))){
                                PPayRefund.setRefundStatus(FinalUtil.PAY_REFUND_FAILUE);//退款失败
                                retJson = new ResponseJson(ErrorInfoEnum.PAY_RESULT_TYPE,"原交易不允许撤销或退货");
                                PPayRefund.setRefundEndTime(String.valueOf(new SimpleDateFormat("yyyyMMddHHmmss").parse(refund.get("fintime")).getTime()));
                            }else if("1001".equals(refund.get("trxstatus"))&&"SUCCESS".equals(refund.get("retcode"))){
                                PPayRefund.setRefundStatus(FinalUtil.PAY_REFUND_FAILUE);//退款失败
                                retJson = new ResponseJson(ErrorInfoEnum.PAY_RESULT_TYPE,"原交易不存在");
                                PPayRefund.setRefundEndTime(String.valueOf(new SimpleDateFormat("yyyyMMddHHmmss").parse(refund.get("fintime")).getTime()));
                            }else if("3054".equals(refund.get("trxstatus"))&&"SUCCESS".equals(refund.get("retcode"))){
                                PPayRefund.setRefundStatus("2");//交易异常,请查询交易
                                PPayRefund.setRefundEndTime(String.valueOf(new SimpleDateFormat("yyyyMMddHHmmss").parse(refund.get("fintime")).getTime()));
                                retJson = new ResponseJson(ErrorInfoEnum.PAY_DATA_TYPE,"");

                            }else{
                                PPayRefund.setRefundStatus(FinalUtil.PAY_REFUND_FAILUE);
                                retJson = new ResponseJson(ErrorInfoEnum.FAIL_REFUND,refund.get("errmsg"));
                                PPayRefund.setRefundEndTime(String.valueOf(new SimpleDateFormat("yyyyMMddHHmmss").parse(refund.get("fintime")).getTime()));
                            }
                            //保存交易退款数据
                            pPayRefundService.save(PPayRefund);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        return retJson = new ResponseJson(ErrorInfoEnum.FAIL_REFUND, e.toString());
                    }
                }
            } else {
                retJson = new ResponseJson(ErrorInfoEnum.PARAMS_TYPE_ERROR, "请求金额");
            }
        }else {
            //==========退款请求金额等于订单总额 & 小于订单总额==========
            if (Integer.valueOf(pPay.getPayAmount()) - Integer.valueOf(refundAmount) >= 0) {
                //==================交易日期在当天内，并且退款金额与支付金额相同============
                if (MyDateUtil.isThisTime(Long.valueOf(pPay.getPayEndTime()), MyDateUtil.format_yyyy_MM_dd) && Integer.valueOf(pPay.getPayAmount()) - Integer.valueOf(refundAmount) == 0) {
                    //================通联撤销处理：保存撤销数据==================
                    logger.info("================请求金额通联撤销开始================");
                    PPayRefund payCancel = new PPayRefund();
                    payCancel.setDeleteFlg("0");//删除标识 0代表未删除
                    payCancel.setCreatedDate(new Date());
                    payCancel.setRefundAmount(refundAmount);//撤销金额
                    payCancel.setRefundStartTime(String.valueOf(System.currentTimeMillis()));//撤销动作开始时间
                    payCancel.setOldTrxid(pPay.getTrxid());//原订单在收银宝的流水号，用于查账，撤销，退款
                    payCancel.setPayGuid(paymentId);//订单guis
                    //==================执行交易撤销================
                    try {
                    /*
                     * refundAmount 退款金额
                     * reqsn 随机数
                     * pPay.getTrxid() 原交易收银宝平台流水号
                     *oldreqsn	原交易单号	原交易的商户交易单号
                     */
                        logger.info("当天撤销请求参数：payCancel"+payCancel.toString()+" pPay"+pPay.toString()+" pPayCust"+pPayCust.toString());
                        Map<String, String> cancel = callOut_tlPublicService.cancel(Long.valueOf(refundAmount), reqsn, pPay.getTrxid(), "",pPayCust);
                        System.out.println(cancel);
                        logger.info("当天撤销响应参数"+cancel.toString());
                        if("0000".equals(cancel.get("trxstatus"))){
                            payCancel.setTrxid(cancel.get("trxid"));//交易撤销流水单号
                            payCancel.setRefundStatus(FinalUtil.PAY_REFUND_SUCCESS);//退款状态 0表示成功
                            //保存交易撤销数据
                            pPayRefundService.save(payCancel);
                        }else {
                            //保存交易撤销数据
                            retJson = new ResponseJson(ErrorInfoEnum.PAY_DATA_TYPE,"");
                            payCancel.setRefundStatus(FinalUtil.PAY_REFUND_FAILUE);
                        }
                        pPayRefundService.save(payCancel);
                    } catch (Exception e) {
                        e.printStackTrace();
                        return retJson = new ResponseJson(ErrorInfoEnum.FAIL_REFUND, e.toString());
                    }
                }
                //==================交易日期在大于今天小于88天内============
                if (MyDateUtil.getDayDiffFromToday1(pPay.getPayEndTime())&& Integer.valueOf(pPay.getPayAmount()) - Integer.valueOf(refundAmount) == 0) {
                    //================存储退款数据==================
                    logger.info("================请求金额退款开始================");
                    PPayRefund PPayRefund = new PPayRefund();
                    PPayRefund.setDeleteFlg("0");//删除标识 0代表未删除
                    PPayRefund.setCreatedDate(new Date());
                    PPayRefund.setRefundAmount(refundAmount);//撤销金额
                    PPayRefund.setRefundStartTime(String.valueOf(System.currentTimeMillis()));//撤销动作开始时间
                    PPayRefund.setOldTrxid(pPay.getTrxid());//原订单在收银宝的流水号，用于查账，撤销，退款
                    PPayRefund.setPayGuid(paymentId);//订单guis
                    pPayRefund.setNotifyUrl(callIn_outPayReqInRequest.getNotifyUrl());
                    //==================执行退款===============
                    try {
                    /*
                     * refundAmount 退款金额
                     * reqsn 随机数
                     * pPay.getTrxid() 原交易收银宝平台流水号
                     *oldreqsn	原交易单号	原交易的商户交易单号
                     */
                        logger.info("隔天退款请求参数：PPayRefund"+refundAmount+" pPay"+pPay.getTrxid()+" pPayCust"+pPayCust.toString());
                        Map<String, String> refund = callOut_tlPublicService.refund(Long.valueOf(refundAmount), reqsn, pPay.getTrxid(), "",pPayCust);
                        logger.info("隔天退款响应参数："+refund.toString());
                        if (refund.keySet().contains("errmsg") && refund.get("errmsg").contains("余额不足")) {
                            retJson = new ResponseJson(ErrorInfoEnum.FAIL_REFUND, "退款账户余额不足");
                            PPayRefund.setTrxid(refund.get("trxid"));//交易撤销流水单号
                            PPayRefund.setRefundStatus(FinalUtil.PAY_REFUND_FAILUE);
                            PPayRefund.setRefundEndTime(String.valueOf(new SimpleDateFormat("yyyyMMddHHmmss").parse(refund.get("fintime")).getTime()));
                        } else {
                            if("0000".equals(refund.get("trxstatus"))){
                                PPayRefund.setTrxid(refund.get("trxid"));//交易撤销流水单号
                                PPayRefund.setRefundStatus(FinalUtil.PAY_REFUND_SUCCESS);
                                PPayRefund.setRefundEndTime(String.valueOf(new SimpleDateFormat("yyyyMMddHHmmss").parse(refund.get("fintime")).getTime()));
                                //保存交易退款数据
                                pPayRefundService.save(PPayRefund);
                            }else if ("2000".equals(refund.get("trxstatus"))||"2008".equals(refund.get("trxstatus"))){
                                PPayRefund.setTrxid(refund.get("trxid"));//交易撤销流水单号
                                PPayRefund.setRefundStatus("2");
                                PPayRefund.setRefundEndTime(String.valueOf(new SimpleDateFormat("yyyyMMddHHmmss").parse(refund.get("fintime")).getTime()));
                                //保存交易退款数据
                                pPayRefundService.save(PPayRefund);
                            }else {
                                PPayRefund.setRefundStatus(FinalUtil.PAY_REFUND_FAILUE);
                                retJson = new ResponseJson(ErrorInfoEnum.PAY_DATA_TYPE,"");
                            }
                            //保存交易退款数据
                            pPayRefundService.save(PPayRefund);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        return retJson = new ResponseJson(ErrorInfoEnum.FAIL_REFUND, e.toString());
                    }
                }
            } else {
                retJson = new ResponseJson(ErrorInfoEnum.PARAMS_TYPE_ERROR, "请求金额");
            }
        }

        return retJson;
    }

    /**
     * 根据小区sfid查询通联账户信息
     * @param estateGuid
     * @return
     */
    public PPayCust getTLMessage(String estateGuid ,String payType){
        Map<String,String> pMap = new HashMap<String,String>();
        pMap.put("estateGuid",estateGuid);
        pMap.put("payType",payType);
        return pPayCustService.getBySfGuid(pMap);
    }
}
